feat: client.agent() default-agent support across all SDKs#19
Merged
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces DefaultAgentHandle class that auto-creates a chat conversation (POST /api/v1/assistants/chatConversations) when no conversation_id is supplied, then calls /v1/agents/invoke with agentType=PLANNER and agentMode=CHAT_MODE, mirroring the chat UI flow. Also adds test_default_agent.py with two tests that currently fail because client.agent() still requires a name argument — wiring is deferred to Task 6. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mirrors the chat UI flow: auto-creates a chat conversation via POST /api/v1/assistants/chatConversations, then calls the new /v1/agents/invoke (sync) or /v1/agents/run (SSE) endpoints with agentType=PLANNER, agentMode=CHAT_MODE. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors the Python SDK and the chat UI flow: auto-creates a chat conversation via POST /api/v1/assistants/chatConversations, then calls /v1/agents/invoke (sync) or /v1/agents/run (SSE) with agentType=PLANNER, agentMode=CHAT_MODE. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors the Python and TypeScript SDKs and the chat UI flow: auto-creates a chat conversation via POST /api/v1/assistants/chatConversations, then calls /api/v1/agents/invoke (sync) or /api/v1/agents/run (SSE) with agentType=PLANNER, agentMode=CHAT_MODE. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors the SDK pattern: auto-create chat conversation, then call /v1/agents/invoke (sync) or /v1/agents/run (SSE) with PLANNER/CHAT_MODE. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When enabled, the node uses the platform's default agent (PLANNER / CHAT_MODE) instead of requiring an agent name. Mirrors client.agent() (no-arg) on the TypeScript SDK. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add examples of the no-arg client.agent() path (PLANNER / CHAT_MODE) to the top-level CLAUDE.md API Pattern block and all per-SDK READMEs that contain a quick-start example. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Use Default Agent toggle requires client.agent() (no-arg) which landed in the TS SDK at 0.1.2. Pinning ^0.1.1 would let a fresh install resolve the older SDK at runtime and break the new path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Backend now separates Sender.SYSTEM (thinking) and Sender.ASSISTANT (final body) messages in the sync invoke flow, exposing them as a new thinkingSteps field on InvokeAgentResponse. Surfaced as thinking_steps (Python, Rust) / thinkingSteps (TS, Java, n8n) on the SDK's InvokeResponse model. Backward-compatible: defaults to [] when the backend doesn't supply the field. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Empty stubs for AgentsAPI, BotsAPI, PersonasAPI, AbilitiesAPI, and MemoriesAPI. Methods land in subsequent commits. __init__.py is a docstring-only module — callers import from canonical paths. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…odels Adds memory models to ai_sdk.models: - MemoryType, MemoryScope, MemoryVisibility enums - CreateContextMemoryRequest with to_api_dict() that flattens visibility -> shareConfig.visibility on the wire - ContextMemory.from_dict() that flattens shareConfig.visibility back to a top-level visibility field for ergonomics - MemorySearchHit / MemorySearchResults parsed from OpenSearch shape Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds DELETE method to HTTPClient (sync + async) for soft/hard delete. Implements MemoriesAPI with sync and async variants of every operation. Search uses the NLQ hybrid endpoint at /api/v1/hybrid/nlq/search with filters serialized as JSON query params. The MemoryList type alias works around the type checker conflating the list method with the builtin list type. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…classes AgentsAPI, BotsAPI, PersonasAPI, AbilitiesAPI each holds its own HTTP clients and exposes list/get/create/etc. AgentsAPI takes a back-reference to AISdk so create() can resolve persona and ability names via the new namespaces. Pagination helper is duplicated per file to keep each namespace self-contained — extract if a fifth namespace appears. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rewrites AISdk to expose: - client.agents (list, create) + async variants - client.bots (list, get) + async variants - client.personas (list, get, create) + async variants - client.abilities (list, get) + async variants - client.memories (list, get, create, delete, search) + async variants Removes: client.list_agents/create_agent, client.list_bots/get_bot, client.list_personas/get_persona/create_persona, client.list_abilities/ get_ability, plus all aXxx async variants. client.agent(name) is unchanged — it returns an AgentHandle. client.mcp is unchanged. Updates langchain integration code and all unit tests to use the new namespace API. Modernizes 3 persona async-error tests from the deprecated asyncio.get_event_loop() pattern to asyncio.run(). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Adds memory models to package-level __all__ and __init__.py re-exports so users can `from ai_sdk import ContextMemory, ...` - Adds integration test that round-trips create -> get -> list -> search -> delete against a real instance (gated on AI_SDK_HOST and AI_SDK_TOKEN) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Adds CHANGELOG.md with the breaking-change migration table for all four SDKs (Python, TypeScript, Java, Rust CLI) and the new client.memories namespace. - Updates CLAUDE.md API Pattern section with namespace examples. - Updates docs/quickstart.md, docs/async.md, docs/standalone.md to use client.<entity>.<verb>() form. - Updates cookbook agent-config docs (gdpr-dsar-compliance, dbt-pr-review, dq-failure-slack-notifications). - Updates n8n integration test to use client.agents.list(). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds list/get/create/delete/search subcommands under `ai-sdk memories`, mirroring the Phase 1 Python MemoriesAPI surface. Hits /api/v1/contextCenter/memories for CRUD and /api/v1/hybrid/nlq/search for hybrid NLQ search over the contextMemory index. The wire format follows the platform schema: memoryType/memoryScope as explicit enum strings, visibility nested under shareConfig on requests and flattened back via custom Deserialize on responses, and tag FQNs wrapped in the TagLabel envelope (Manual/Confirmed/Classification). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the model layer for the Java memories namespace: - MemoryType, MemoryScope, MemoryVisibility enums (with @jsonvalue serialization to camelCase wire values like "Preference", "EntityScoped", "Private") - CreateContextMemoryRequest with builder + toApiMap() that re-nests visibility under shareConfig and wraps tags as TagLabels (labelType=Manual, state=Confirmed, source=Classification) - ContextMemory POJO with a static fromMap() factory that flattens shareConfig.visibility back to a top-level visibility field - MemorySearchHit + MemorySearchResults with MemorySearchResults fromOpenSearch() parser for the OpenSearch hits.total.value / hits.hits[i]._source/_score response shape Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Introduces an api/ package with one namespace class per entity domain: - AgentsApi: list / create (resolves persona + ability names via the parent AISdk back-reference) - BotsApi: list / get - PersonasApi: list / get / create - AbilitiesApi: list / get - MemoriesApi: list (paginated) / get / create / delete / search (hybrid NLQ search via /api/v1/hybrid/nlq/search), backed by two AISdkHttpClient instances — one rooted at /api/v1/contextCenter/ memories for CRUD and one rooted at /api/v1 for search Adds the supporting low-level helpers on AISdkHttpClient: - A new constructor that accepts a base path so additional clients can target the memories and search endpoints - Generic getMap / postMap / delete (path, params) methods used by the namespace classes for arbitrary JSON requests against any base URL Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Converts AISdk's per-entity flat methods to namespaced accessors that return the new api/ package classes, matching the Python and TypeScript SDK shape. - AISdk now constructs three AISdkHttpClient instances (default, memories CRUD, hybrid search) and exposes agents() / bots() / personas() / abilities() / memories() accessors - Removes flat methods listAgents / createAgent / listBots / getBot / listPersonas / getPersona / createPersona / listAbilities / getAbility — callers must use client.agents().list() etc. - agent(name) factory and the no-arg agent() default-agent factory are unchanged - AISdkTest and IntegrationTest are updated to the namespace form - Adds MemoriesApiTest covering list pagination, primaryEntityFqn filtering, limit, get, create (toApiMap shape including tag wrapping and shareConfig nesting), delete (soft + hard), search parameters, search filter JSON serialization, OpenSearch response parsing, and ContextMemory.fromMap visibility flattening Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the memory data model surface for the upcoming MemoriesApi namespace: MemoryType / MemoryScope / MemoryVisibility string-literal unions, ContextMemory, MemorySearchHit, MemorySearchResults, and CreateContextMemoryRequest. Mirrors the Pydantic models in the Python SDK and is purely additive — existing exports are unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Introduces a new src/api/ directory with one namespace class per entity domain: - AgentsApi: list / create (resolves persona + ability names via the parent AISdk back-reference) - BotsApi: list / get - PersonasApi: list / get / create - AbilitiesApi: list / get - MemoriesApi: list (paginated, optionally filtered by primaryEntityFqn) / get / create / delete (soft + hard) / search (hybrid NLQ via /api/v1/hybrid/nlq/search), backed by two HttpClient instances — one rooted at /api/v1/contextCenter/memories for CRUD and one at /api/v1 for the search endpoint. Adds the supporting helpers on HttpClient: a generic delete() method, boolean query-parameter values (for hardDelete), entityType / entityName on public verb methods so namespaces can surface typed 404 errors, and a parseBody() helper that returns void for empty responses. The existing flat methods on AISdk remain in place for now; the next commit replaces them with namespace accessors. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…sors Drops the listAgents / createAgent / listBots / getBot / listPersonas / getPersona / createPersona / listAbilities / getAbility surface from AISdk and replaces it with composed namespace fields: client.agents.list() / client.agents.create(req) client.bots.list() / client.bots.get(name) client.personas.list() / client.personas.get(name) / client.personas.create(req) client.abilities.list() / client.abilities.get(name) client.memories.list() / .get / .create / .delete / .search The agent handle factory (client.agent(name)) is unchanged. AISdk now constructs one HttpClient per entity rooted at its API path; the namespace classes issue plain relative requests against that base URL. The legacy getAbsolute / postAbsolute helpers on HttpClient are removed since no caller needs them anymore. Tests: client.test.ts and integration.test.ts mechanically renamed flat-method calls to namespace form. README.md updated to show the namespace API and adds a Context Memories section. This is a breaking change at v0.1.x (documented in CHANGELOG.md / spec). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brainstorming/plan artifacts live alongside the code locally but are not part of the merged history. Mirrors the existing docs/plans/** ignore pattern. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a new "Context Memories" section to: - README.md (root) — concise pitch + Python/TS/Java/CLI examples for the create -> list -> search -> delete cycle, including filter usage. - python/README.md — full examples (sync + async), enum cheatsheet, stored-fields table. - java/README.md — namespace examples for all entities (replaces the old flat method calls that were missed in the Phase 3 refactor) plus a Memories section with builder usage and the stored-fields table. - cli/README.md — `ai-sdk memories` subcommand reference with all flags, enum values, and a --json example. The TypeScript README already had a Memories section from Phase 2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a synthetic "AskCollate (default)" entry as the first item in the chat agent selection menu. Selecting it routes the chat to the platform's default agent (use_default = true) instead of a named dynamic agent. The menu is now useful even when there are no API-enabled named agents. Behaviour: - Menu always has AskCollate at the top with description "The platform's default agent — no specific agent selected" - Selecting AskCollate sets use_default=true and labels the header "AskCollate" - Selecting a named agent sets use_default=false (clears the flag if the chat was previously in default mode) Adds 4 unit tests covering the prepend, the empty-list case, and both selection paths. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each thinking event from the stream is a discrete reasoning step. Previously they were concatenated without separators, so they all collapsed onto a single rendered line — hard to read. - TUI: append_thinking_content now inserts a newline between non-empty steps when the buffer doesn't already end in one. The rendering path uses .lines() so each step shows on its own row. - invoke --thinking: print each step with println!() (after trimming trailing whitespace) so each lands on its own line. Adds 2 unit tests covering the separator-injection and the case where a step already ended in a newline (no extra blank line). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related TUI improvements:
1. Markdown links: previously the renderer fell into the catch-all
_ => {} arm for Tag::Link / TagEnd::Link, so the visible label
rendered with no styling and the URL was dropped. Now the label
gets a blue + underlined style, and " (url)" is appended in
dimmed text afterwards. Nested links are supported via a URL
stack.
2. Thinking steps: the live-streaming and persisted thinking blocks
were rendered as raw lines, so any markdown the agent emitted
(links, bold, code) leaked through unstyled. They now go through
a new render_markdown_dimmed() that runs the full markdown
pipeline and then collapses every foreground colour to DarkGray
while preserving bold/italic/underline modifiers. Each rendered
line is indented two spaces under the "Thinking:" header.
Adds 3 unit tests: link label + url presence, link underline modifier,
and dimmed-renderer colour override + modifier preservation.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The audit found two stale spots in docs and examples:
1. docs/API_REFERENCE.md — every per-SDK method table still showed
the old flat methods (client.list_agents, client.listAgents,
client.listAgents() in Java) and was missing the new memories
namespace entirely. The Server Endpoint Map missed the memory
CRUD and hybrid search endpoints. Data Models section had no
ContextMemory / CreateContextMemoryRequest / MemorySearchResults /
EntityReference. Feature Parity Matrix missed the Memories row
and the default-agent feature.
2. cookbook/{gdpr-dsar-compliance,dbt-pr-review,dq-failure-slack-
notifications}/agent-config.md — the TypeScript and Java code
blocks still called client.createAgent(...). Updated to
client.agents.create(...) for TS and client.agents().create(...)
for Java.
Verified: a repo-wide grep for flat-method patterns now returns
zero hits outside the CHANGELOG migration table and gitignored
local design docs. All linters pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Long agent runs (>2 min) were being cut mid-stream because each SDK's HTTP client applied its standard request timeout to SSE response bodies. The failure surfaces as a decode/connection error, masking the timeout as the real cause. - Rust CLI: separate streaming reqwest client with no timeout - Python: separate httpx client with read=None for post_stream (sync + async) - TypeScript: dropped AbortController deadline from postStream - Java: only connectTimeout was set; added Javadoc warnings to lock that in Default timeout for non-streaming calls bumped 120 -> 900s across all four. Also adds 'ai-sdk chat --debug [PATH]' to the Rust CLI: writes SSE event traces (each event, message, and the underlying error + unparsed buffer when a stream dies) to a file. Defaults to ~/.ai-sdk/chat-debug.log. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
49d9a45 to
a7df37e
Compare
Three independent CI failures caused by tool versions newer than what local dev had cached: - Rust: clippy 1.95 expanded `collapsible_match` to flag arms whose body is a single conditional. Convert 6 such arms in `cli/src/tui/*` to use match guards. - Python: ty 0.0.33 only recognizes the alias name from `Field(alias=...)` as a valid kwarg, ignoring `populate_by_name`/`validate_by_name`. Replace explicit per-field aliases with `alias_generator=to_camel` on the model_config; ty then accepts snake_case kwargs while pydantic still produces/parses camelCase via the auto-generated aliases. - n8n: `npm install` was pulling `@openmetadata/ai-sdk` from the npm registry, which lacks `thinkingSteps`. Switch the dep to `file:../typescript` so CI builds against the local SDK (matches what the local dev symlink already does). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Minor bump: SSE timeout handling changed across all SDKs (separate streaming client / no request deadline on streams), default request timeout 120s -> 900s, and the Rust CLI gained `chat --debug [PATH]` for SSE event tracing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds default-agent support across all 5 SDKs:
client.agent()(no name) now invokes the platform's default chat agent (PLANNER/CHAT_MODE), mirroring the chat UI's flow.client.agent("Name")for dynamic agents is unchanged.Pairs with backend PR open-metadata/openmetadata-collate#3936 (which adds the new
POST /v1/agents/invokeendpoint and extracts the shared SSE collector).What changed
AISdk.agent(name=None)returns aDefaultAgentHandlethat auto-creates a chat conversation and invokes/v1/agents/invoke(sync) or/v1/agents/run(SSE). 4 unit tests (sync, sync-with-conversation-id, streaming, async). Schema regenerated forPLANNER/INVENTORY.client.agent()overload returns aDefaultAgentHandle. 2 unit tests.client.agent()no-arg overload returns aDefaultAgentHandle. 5 Mockito tests.--default/-Dflag onInvokeandChatsubcommands. 4 wiremock tests.^0.1.2.docs/superpowers/.API examples
Coordination
This PR depends on the backend
POST /v1/agents/invokeendpoint shipping in open-metadata/openmetadata-collate#3936 — the new sync default-agent path will 404 until that lands.The TypeScript SDK must be published at
0.1.2(or newer) before the n8n node can install cleanly from npm; the local symlink works for development. The n8npackage.jsonalready pins^0.1.2so a fresh install will refuse the older SDK that lacks the no-arg overload.Test plan
cd python && pytest --ignore=tests/integration— all green (180+ tests)cd typescript && npm test— all green (40 tests)cd java && mvn test— all green (49 tests)cd cli && cargo test— all greencd n8n-nodes-metadata && npm run build && npm run lint— clean (requires npm-linked TS SDK 0.1.2)client.agent().call(...)against a real instance viamake test-integrationFollow-ups (from final code review, non-blocking)
AISdkHttpClientdirectly; other SDKs cover wire format end-to-end)useDefaultAgenttogglewip(python): ...+ the next feat commit before merging for cleaner historyDefaultAgentHandlefromextends AgentHandleto composition (mildly fragile bypass of parent__init__)🤖 Generated with Claude Code